﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using ScreenMonitor.Common;
using ScreenMonitor.ServerLib.OutputCollector;
using ScreenMonitor.ServerLib.Plugin;
using ScreenMonitor.Common.File;
using FrameWork.Setting;
using FrameWork.Output;
using FrameWork.Plugin;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using FrameWork.Design;

namespace ScreenMonitor.ServerLib
{
    /// <summary>
    /// 为服务器状态标识提供枚举
    /// </summary>
    public enum ServerState
    {
        Created,
        Inited,
        Started,
        Stoped,
        Crashed
    }
    /// <summary>
    /// 表示服务端当前的初始化状态
    /// </summary>
    public sealed class ServerInitState
    {
        /// <summary>
        /// 表示服务端的初始化步骤
        /// </summary>
        public ServerInitSetp Setp { get;internal set; }
        /// <summary>
        /// 表示服务端当前步骤是否已经完成
        /// </summary>
        public bool IsInited { get;internal set; }
    }
    /// <summary>
    /// 表示服务端当前初始化的步骤
    /// </summary>
    public enum ServerInitSetp
    {
        Setting,
        Output,
        GlobalObject,
        FilePool,
        Tcp,
        Udp,
        Compelete
    }
    public static class ServerMain
    {

        #region========私有变量========

        /// <summary>
        /// 服务端状态
        /// </summary>
        private static ServerState State = ServerState.Created;

        #endregion

        #region==========属性==========

        /// <summary>
        /// 表示服务端当前的初始化步骤
        /// </summary>
        public static ServerInitState InitState { get;private set; }

        #endregion

        #region========公有函数========

        /// <summary>
        /// 获取服务端状态
        /// </summary>
        /// <returns></returns>
        public static ServerState GetState()
        {
            return State;
        }
        
        /// <summary>
        /// 初始化服务端
        /// </summary>
        /// <returns></returns>
        public static bool Init()
        {
            if (State != ServerState.Created)
                return false;
            InitState = new ServerInitState();

            #region=======设定池初始化=======

            InitState.Setp = ServerInitSetp.Setting;
            InitState.IsInited = false;
            SettingPool.Init(new INISettingOperator(Environment.CurrentDirectory + @"\Setting.ini"));
            InitState.IsInited = true;

            #endregion

            #region=======输出池初始化=======

            InitState.Setp = ServerInitSetp.Output;
            InitState.IsInited = false;
            OutputPool.Init();
            InitState.IsInited = true;

            #endregion

            #region======全局变量初始化======

            InitState.Setp = ServerInitSetp.GlobalObject;
            InitState.IsInited = false;

            //=====对象初始化=====//
            CommandObjects.GZipDataCompressor = new MyServer.Common.GZipDataCompressor();

            //=====设定初始化=====//
            ServerObjects.GlobalSettingIpPortEditItem = new SettingPropertyEditorItem(@"全局设定\适配器与端口绑定", null, typeof(ServerGlobalSettingIpPort));
            ServerObjects.GlobalSettingScreenViewImgItem=new SettingPropertyEditorItem(@"全局设定\屏幕监控\图像设定",null,typeof(ServerGlobalSettingScreenViewImg));
            SettingPool.RegisterEditor(ServerObjects.GlobalSettingIpPortEditItem);
            SettingPool.RegisterEditor(ServerObjects.GlobalSettingScreenViewImgItem);
            SettingPool.LoadSetting();
            SettingPool.AcceptSetting();

            NetworkInterface Interface = NetworkInterfaceConverter.GetAdapter(ServerGlobalSettingIpPort.ServerBindAdapter);
            ServerGlobalSettingIpPort.ServerIpAddr = NetworkInterfaceConverter.GetIpV4Address(Interface);
            ServerGlobalSettingIpPort.ServerMulticastIpAddr = NetworkInterfaceConverter.GetMulticastIpV4Address(Interface);

            InitState.IsInited = true;

            #endregion

            #region=======文件池初始化=======

            InitState.Setp = ServerInitSetp.FilePool;
            InitState.IsInited = false;

            //=====对象初始化=====//
            FilePool.Init();
            FilePool.NeedToRequestEvent += FilePool_NeedToRequestEvent;

            //=====设定初始化=====//
            ServerObjects.FilePoolSettingEditorItem = new SettingPropertyEditorItem(@"全局设定\服务端对象\文件池", null, typeof(FilePool));
            SettingPool.RegisterEditor(ServerObjects.FilePoolSettingEditorItem);
            SettingPool.LoadSetting();
            SettingPool.AcceptSetting();

            InitState.IsInited = true;

            #endregion

            #region======Tcp 相关初始化======

            InitState.Setp = ServerInitSetp.Tcp;
            InitState.IsInited = false;

            //=====对象初始化=====//
            CommandObjects.TcpCommandCenter = new TcpCommandCenter(CommandObjects.TcpCenter);
            CommandObjects.TcpCenter = new MyServer.TcpIP.TcpIpCenter(
                new IPEndPoint(ServerGlobalSettingIpPort.ServerIpAddr, ServerGlobalSettingIpPort.ServerTcpListenPort),
                CommandObjects.TcpCommandCenter,
                CommandObjects.GZipDataCompressor);
            CommandObjects.TcpCenter.Listener.ListenTimeOut += Listener_ListenTimeOut;
            CommandObjects.TcpCenter.ConnectionManager.NewConnectionJoin += ConnectionManager_NewConnectionJoin;
            CommandObjects.TcpCommandCenter.OperateCommand += TcpCommandCenter_OperateCommand;

            //=====设定初始化=====//
            ServerObjects.TcpIpConnectManagerSettingEditorItem = new SettingPropertyEditorItem(@"TcpIP设定\连接管理器", CommandObjects.TcpCenter.ConnectionManager, CommandObjects.TcpCenter.ConnectionManager.GetType());
            ServerObjects.TcpIpDataSenderSettingEditorItem = new SettingPropertyEditorItem(@"TcpIP设定\数据发送器", CommandObjects.TcpCenter.Sender, CommandObjects.TcpCenter.Sender.GetType());
            ServerObjects.TcpIpDataReaderSettingEditorItem = new SettingPropertyEditorItem(@"TcpIP设定\数据接收器", CommandObjects.TcpCenter.Reader, CommandObjects.TcpCenter.Reader.GetType());
            ServerObjects.TcpIpDataOperaterSettingEditorItem = new SettingPropertyEditorItem(@"TcpIP设定\数据处理器", CommandObjects.TcpCenter.Operator, CommandObjects.TcpCenter.Operator.GetType());
            ServerObjects.TcpIpDataListenerSettingEditorItem = new SettingPropertyEditorItem(@"TcpIP设定\数据监听器", CommandObjects.TcpCenter.Listener, CommandObjects.TcpCenter.Listener.GetType());
            SettingPool.RegisterEditor(ServerObjects.TcpIpConnectManagerSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.TcpIpDataSenderSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.TcpIpDataReaderSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.TcpIpDataOperaterSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.TcpIpDataListenerSettingEditorItem);
            SettingPool.LoadSetting();
            SettingPool.AcceptSetting();

            //=====输出初始化=====//
            ServerObjects.SenderOutputCollector = new DataSenderOutputCollector(CommandObjects.TcpCenter.Sender);
            ServerObjects.ReaderOutputCollector = new DataReaderOutputCollector(CommandObjects.TcpCenter.Reader);
            ServerObjects.CommandCenterOutputCollector = new CommandCenterOutputCollector(CommandObjects.TcpCommandCenter);
            ServerObjects.ConnectManagerOutputCollector = new ConnectManagerOutputCollector(CommandObjects.TcpCenter.ConnectionManager);
            ServerObjects.DataListenerOutputCollector = new DataListenerOutputCollector(CommandObjects.TcpCenter.Listener);
            OutputPool.RegisterCollector(ServerObjects.SenderOutputCollector);
            OutputPool.RegisterCollector(ServerObjects.ReaderOutputCollector);
            OutputPool.RegisterCollector(ServerObjects.CommandCenterOutputCollector);
            OutputPool.RegisterCollector(ServerObjects.ConnectManagerOutputCollector);
            OutputPool.RegisterCollector(ServerObjects.DataListenerOutputCollector);

            InitState.IsInited = true;

            #endregion

            #region======Udp 相关初始化======

            InitState.Setp = ServerInitSetp.Udp;
            InitState.IsInited = false;

            //=====对象初始化=====//
            CommandObjects.UdpCommandCenter = new UdpCommandCenter(CommandObjects.UdpCenter);
            CommandObjects.UdpCenter = new MyServer.Udp.UdpCenter(CommandObjects.UdpCommandCenter);
            CommandObjects.UdpCommandCenter.LocalUdpClient = new UdpClient(new IPEndPoint(ServerGlobalSettingIpPort.ServerIpAddr, ServerGlobalSettingIpPort.ServerUdpListenPort));
            UdpCommandOperater.LocalUdpClient = CommandObjects.UdpCommandCenter.LocalUdpClient;
            CommandObjects.UdpCommandCenter.OperateCommand += UdpCommandCenter_OperateCommand;

            //=====设定初始化=====//
            ServerObjects.UdpConnectManagerSettingEditorItem = new SettingPropertyEditorItem(@"Udp设定\连接管理器", CommandObjects.UdpCenter.ConnectionManager, CommandObjects.UdpCenter.ConnectionManager.GetType());
            ServerObjects.UdpDataSenderSettingEditorItem = new SettingPropertyEditorItem(@"Udp设定\数据发送器", CommandObjects.UdpCenter.Sender, CommandObjects.UdpCenter.Sender.GetType());
            ServerObjects.UdpDataReaderSettingEditorItem = new SettingPropertyEditorItem(@"Udp设定\数据接收器", CommandObjects.UdpCenter.Reader, CommandObjects.UdpCenter.Reader.GetType());
            ServerObjects.UdpDataOperaterSettingEditorItem = new SettingPropertyEditorItem(@"Udp设定\数据处理器", CommandObjects.UdpCenter.Operator, CommandObjects.UdpCenter.Operator.GetType());
            ServerObjects.UdpDataListenerSettingEditorItem = new SettingPropertyEditorItem(@"Udp设定\数据监听器", CommandObjects.UdpCenter.Listener, CommandObjects.UdpCenter.Listener.GetType());
            SettingPool.RegisterEditor(ServerObjects.UdpConnectManagerSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.UdpDataSenderSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.UdpDataReaderSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.UdpDataOperaterSettingEditorItem);
            SettingPool.RegisterEditor(ServerObjects.UdpDataListenerSettingEditorItem);
            SettingPool.LoadSetting();
            SettingPool.AcceptSetting();

            InitState.IsInited = true;

            #endregion

            #region======插件相关初始化======

            ServerPluginLoader.LoadPlugin(Environment.CurrentDirectory + @"\Plugins");

            foreach(IServerPlugin Plu in PluginPool.GetPlugins())
            {

                SettingPool.RegisterEditor(Plu.GetSettingEditors());
                SettingPool.LoadSetting();
                SettingPool.AcceptSetting();

                OutputPool.RegisterCollector(Plu.GetOutputCollectors());

                Plu.Init();
                Plu.Enable();

            }

            #endregion

            State = ServerState.Inited;
            InitState.Setp = ServerInitSetp.Compelete;

            OutputPool.Start();

            return true;
        }


        /// <summary>
        /// 启动服务端
        /// </summary>
        /// <returns></returns>
        public static bool Start()
        {
            if (State == ServerState.Started || State == ServerState.Created)
                return false;
            bool issuc = CommandObjects.TcpCenter.Start() && CommandObjects.UdpCenter.Start();
            if (issuc)
            {
                State = ServerState.Started;
                CommandObjects.UdpCommandCenter.SendCommand(CommandType.ServerStarted, new IPEndPoint(ServerGlobalSettingIpPort.ServerMulticastIpAddr, ServerGlobalSettingIpPort.ClientUdpListenPort));
                return true;
            }
            else
            {
                State = ServerState.Crashed;
                return false;
            }
        }

        /// <summary>
        /// 停止服务端
        /// </summary>
        /// <returns></returns>
        public static bool Stop(bool isClearQueue = true)
        {
            bool issuc = CommandObjects.TcpCenter.Stop(isClearQueue) && CommandObjects.UdpCenter.Stop();
            OutputPool.Stop();
            if (issuc)
            {
                State = ServerState.Stoped;
                return true;
            }
            else
            {
                State = ServerState.Crashed;
                return false;
            }
        }

        /// <summary>
        /// 重新启动服务端
        /// </summary>
        /// <returns></returns>
        public static bool Restert()
        {
            Stop(true);
            if (State == ServerState.Crashed)
            {
                return false;
            }
            Start();
            if (State == ServerState.Crashed)
            {
                return false;
            }
            return true;
        }

        #endregion

        #region========私有函数========

        static void UdpCommandCenter_OperateCommand(object sender, OperateCommandEventArgs e)
        {
            UdpCommandOperater.RunCommand(e.Package);
        }

        static void TcpCommandCenter_OperateCommand(object sender, OperateCommandEventArgs e)
        {
            TcpCommandOperater.RunCommand(e.Package);
        }

        static void FilePool_NeedToRequestEvent(Common.File.FileRequestEventArgs e)
        {
            if (e.ResponceObject != null)
            {
                CommandObjects.TcpCommandCenter.SendCommandWithData(CommandType.SendFile, e.ResponceObject.ToByte(), (TcpClient)e.ResponceObject.Tag);
            }
        }

        static void ConnectionManager_NewConnectionJoin(object sender, MyServer.Common.ConnectEventArgs e)
        {
            TcpClient c = (TcpClient)e.Connect;
            ClientObject smini = new ClientObject(c);
            smini.InfoStr = c.Client.RemoteEndPoint.ToString();
            smini.State = ClientState.Init;
            ClientManager.AddClient(smini);
        }

        static void Listener_ListenTimeOut(object sender, MyServer.Common.DataListenerEventArgs e)
        {
            TcpClient c = (TcpClient)e.Connect;
            foreach (ClientObject sm in ClientManager.GetAllClient())
            {
                if (sm.Client == c)
                {
                    sm.State = ClientState.DisConnected;
                    return;
                }
            }
        }

        #endregion

    }
}
